/*
 * randlcg.c  Linear Congruential Method, the "minimal standard generator"
 *            Park & Miller, 1988, Comm of the ACM, 31(10), pp. 1192-1201
 */

static char rcsid[] = "@(#)randlcg.c	1.1 15:48:15 11/21/94   EFC";

#include <math.h>
#include <limits.h>

#define ALL_BITS     0xffffffff

static long int randlcg_quotient  = LONG_MAX / 16807L;
static long int randlcg_remainder = LONG_MAX % 16807L;

static long int seed_val = 1L;

long set_seed(long int sd)
{
    return seed_val = sd;
}

long get_seed(void)
{
    return seed_val;
}

unsigned long int randlcg(void) /* returns a random unsigned integer */
{
    if (seed_val <= randlcg_quotient) {
        seed_val = (seed_val * 16807L) % LONG_MAX;
    } else {
        long int high_part = seed_val / randlcg_quotient;
        long int low_part  = seed_val % randlcg_quotient;

        long int test = 16807L * low_part - randlcg_remainder * high_part;

        if (test > 0) {
            seed_val = test;
        } else {
            seed_val = test + LONG_MAX;
        }
    }

    return seed_val;
}

#ifdef TEST_RANDLCG

/*
 * Compile using:  gcc -g -DTEST_RANDLCG -o randlcg randlcg.c
 */

#include <stdio.h>
#include <string.h>

#define TOTAL_BUCKETS   100
#define TOTAL_SAMPLES   10000000

int main(int argc, char **argv)
{
    int i;
    int buckets[TOTAL_BUCKETS];
    unsigned long int value;

    memset(buckets, 0, sizeof(buckets));

    for (i = 0; i < TOTAL_SAMPLES; i++) {
        value = randlcg();
        (buckets[value % TOTAL_BUCKETS])++;
    }

    for (i = 0; i < TOTAL_BUCKETS; i++) {
        printf("bucket[%d] = %d\n", i, buckets[i]);
    }

    return 0;
}

#endif /* TEST_RANDLCG */
